home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpuzzles.3 / xpuzzles / xpuzzles-5.3.1 / xrubik / xmrubik.c < prev    next >
C/C++ Source or Header  |  1996-02-07  |  18KB  |  607 lines

  1. /*
  2. # MOTIF-BASED RUBIK'S CUBE(tm)
  3. #
  4. #  xmrubik.c
  5. #
  6. ###
  7. #
  8. #  Copyright (c) 1993 - 96    David Albert Bagley, bagleyd@hertz.njit.edu
  9. #
  10. #                   All Rights Reserved
  11. #
  12. #  Permission to use, copy, modify, and distribute this software and
  13. #  its documentation for any purpose and without fee is hereby granted,
  14. #  provided that the above copyright notice appear in all copies and
  15. #  that both that copyright notice and this permission notice appear in
  16. #  supporting documentation, and that the name of the author not be
  17. #  used in advertising or publicity pertaining to distribution of the
  18. #  software without specific, written prior permission.
  19. #
  20. #  This program is distributed in the hope that it will be "useful",
  21. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  23. #
  24. */
  25.  
  26. /*
  27.   Version 5: 95/10/06 Xt/Motif
  28.   Version 4: 94/04/07 Xt
  29.   Version 3: 93/05/20 Motif
  30.   Version 2: 92/01/16 XView
  31.   Version 1: 91/01/16 SunView
  32. */
  33.  
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #ifdef VMS
  37. #include <unixlib.h>
  38. #define getlogin cuserid
  39. #else
  40. #ifndef apollo
  41. #include <unistd.h>
  42. #endif
  43. #endif
  44. #include <X11/Intrinsic.h>
  45. #include <X11/StringDefs.h>
  46. #include <X11/Shell.h>
  47. #include <X11/cursorfont.h>
  48. #include <Xm/PanedW.h>
  49. #include <Xm/RowColumn.h>
  50. #include <Xm/Label.h>
  51. #include <Xm/LabelG.h>
  52. #include <Xm/Scale.h>
  53. #include <Xm/ToggleB.h>
  54. #include "Rubik.h"
  55. #include "Rubik2d.h"
  56. #include "Rubik3d.h"
  57. #include "rubik.xbm"
  58. #include "mouse-l.xbm"
  59. #include "mouse-r.xbm"
  60.  
  61. #ifndef SCOREFILE
  62. #define SCOREFILE "/usr/games/lib/mball.scores"
  63. #endif
  64.  
  65. /* The following are in RubikP.h also */
  66. #define MINCUBES 1
  67. #define MAXFACES 6
  68.  
  69. #define MAXCUBES 6
  70. #define MAXRECORD 32767
  71.  
  72. static void Initialize();
  73. static void CallbackRubik();
  74.  
  75. static void PrintRecord();
  76. static int HandleSolved();
  77. static void ReadRecords();
  78. static void WriteRecords();
  79.  
  80. static void CubesSlider();
  81. static void OrientToggle();
  82. static void PracticeToggle();
  83. static void motif_printf();
  84.  
  85. static Arg arg[4];
  86. static Widget moves, record, message, rubik2d, rubik3d, cubes,
  87.   orientSwitch, practiceSwitch;
  88. static int rubikRecord[2][MAXCUBES - MINCUBES + 1], movesDsp = 0;
  89. static char messageDsp[128] = "Welcome";
  90.  
  91. static void usage()
  92. {
  93.   (void) fprintf(stderr, "usage: xmrubik\n");
  94.   (void) fprintf(stderr,
  95.     "\t[-geometry [{width}][x{height}][{+-}{xoff}[{+-}{yoff}]]]\n");
  96.   (void) fprintf(stderr,
  97.     "\t[-display [{host}]:[{vs}]][-fg {color}] [-bg {color}]\n");
  98.   (void) fprintf(stderr,
  99.     "\t[-{border|bd} {color}] [-mono] [-size {int}] [-[no]orient]\n");
  100.   (void) fprintf(stderr,
  101.     "\t[-[no]practice] [-face{0|1|2|3|4|5} {color}]\n");
  102.   exit(1);
  103. }
  104.  
  105. static XrmOptionDescRec options[] = {
  106.   {"-fg",        "rubik.Foreground",    XrmoptionSepArg,    NULL},
  107.   {"-bg",        "*Background",        XrmoptionSepArg,    NULL},
  108.   {"-foreground",    "rubik.Foreground",    XrmoptionSepArg,    NULL},
  109.   {"-background",    "*Background",        XrmoptionSepArg,    NULL},
  110.   {"-border",        "*rubik.pieceBorder",    XrmoptionSepArg,    NULL},
  111.   {"-bd",        "*rubik.pieceBorder",    XrmoptionSepArg,    NULL},
  112.   {"-mono",        "*rubik.mono",        XrmoptionNoArg,        "TRUE"},
  113.   {"-size",        "*rubik.size",        XrmoptionSepArg,    NULL},
  114.   {"-orient",        "*rubik.orient",    XrmoptionNoArg,        "TRUE"},
  115.   {"-noorient",        "*rubik.orient",    XrmoptionNoArg,        "FALSE"},
  116.   {"-practice",        "*rubik.practice",    XrmoptionNoArg,        "TRUE"},
  117.   {"-nopractice",    "*rubik.practice",    XrmoptionNoArg,        "FALSE"},
  118.   {"-face0",        "*rubik.faceColor0",    XrmoptionSepArg,    NULL},
  119.   {"-face1",        "*rubik.faceColor1",    XrmoptionSepArg,    NULL},
  120.   {"-face2",        "*rubik.faceColor2",    XrmoptionSepArg,    NULL},
  121.   {"-face3",        "*rubik.faceColor3",    XrmoptionSepArg,    NULL},
  122.   {"-face4",        "*rubik.faceColor4",    XrmoptionSepArg,    NULL},
  123.   {"-face5",        "*rubik.faceColor5",    XrmoptionSepArg,    NULL},
  124. };
  125.  
  126. int main(argc, argv)
  127.   int argc;
  128.   char *argv[];
  129. {
  130.   Widget toplevel;
  131.   Widget panel, panel2, rowcol, rowcol2, rowcol3, rowcol4;
  132.   Pixmap mouseLeftCursor, mouseRightCursor;
  133.   Pixel fg, bg;
  134.  
  135.   toplevel = XtInitialize(argv[0], "Rubik",
  136.     options, XtNumber(options), &argc, argv);
  137.   if (argc != 1)
  138.     usage();
  139.  
  140.   XtSetArg(arg[0], XtNiconPixmap,
  141.     XCreateBitmapFromData(XtDisplay(toplevel),
  142.       RootWindowOfScreen(XtScreen(toplevel)),
  143.       (char *) rubik_bits, rubik_width, rubik_height));
  144.   XtSetArg(arg[1], XmNkeyboardFocusPolicy, XmPOINTER); /* not XmEXPLICIT */  
  145.   XtSetValues(toplevel, arg, 2);  
  146.   panel = XtCreateManagedWidget("panel", xmPanedWindowWidgetClass, toplevel,
  147.     NULL, 0);
  148.   panel2 = XtVaCreateManagedWidget("panel2", xmPanedWindowWidgetClass, panel,
  149.     XmNseparatorOn, False,
  150.     XmNsashWidth, 1,
  151.     XmNsashHeight, 1,
  152.     NULL);
  153.  
  154.   rowcol = XtVaCreateManagedWidget("Rowcol", xmRowColumnWidgetClass, panel2,
  155.     XmNnumColumns, 2,
  156.     XmNorientation, XmHORIZONTAL,
  157.     XmNpacking, XmPACK_COLUMN,
  158.     NULL);
  159.   XtVaGetValues(rowcol, XmNforeground, &fg, XmNbackground, &bg, NULL);
  160.   mouseLeftCursor = XCreatePixmapFromBitmapData(XtDisplay(rowcol),
  161.     RootWindowOfScreen(XtScreen(rowcol)), mouse_left_bits,
  162.     mouse_left_width, mouse_left_height, fg, bg,
  163.     DefaultDepthOfScreen(XtScreen(rowcol)));
  164.   mouseRightCursor = XCreatePixmapFromBitmapData(XtDisplay(rowcol),
  165.     RootWindowOfScreen(XtScreen(rowcol)), mouse_right_bits,
  166.     mouse_right_width, mouse_right_height, fg, bg,
  167.     DefaultDepthOfScreen(XtScreen(rowcol)));
  168.   XtVaCreateManagedWidget("mouseLeftText", xmLabelGadgetClass, rowcol,
  169.     XtVaTypedArg, XmNlabelString, XmRString, "Move", 5, NULL);
  170.   XtVaCreateManagedWidget("mouseLeft", xmLabelGadgetClass, rowcol,
  171.     XmNlabelType, XmPIXMAP, XmNlabelPixmap, mouseLeftCursor, NULL);
  172.   XtVaCreateManagedWidget("mouseRightText", xmLabelGadgetClass, rowcol,
  173.     XtVaTypedArg, XmNlabelString, XmRString, "Randomize", 10, NULL);
  174.   XtVaCreateManagedWidget("mouseRight", xmLabelGadgetClass, rowcol,
  175.     XmNlabelType, XmPIXMAP, XmNlabelPixmap, mouseRightCursor, NULL);
  176.   XtVaCreateManagedWidget("movesText", xmLabelGadgetClass, rowcol,
  177.     XtVaTypedArg, XmNlabelString, XmRString, "Moves", 6, NULL);
  178.   moves = XtVaCreateManagedWidget("0", xmLabelWidgetClass, rowcol, NULL);
  179.   XtVaCreateManagedWidget("recordText", xmLabelGadgetClass, rowcol,
  180.     XtVaTypedArg, XmNlabelString, XmRString, "Record", 7, NULL);
  181.   record = XtVaCreateManagedWidget("0", xmLabelWidgetClass, rowcol, NULL);
  182.  
  183.   rowcol2 = XtVaCreateManagedWidget("Rowcol2", xmRowColumnWidgetClass, panel2,
  184.     NULL);
  185.   cubes = XtVaCreateManagedWidget("cubes", xmScaleWidgetClass, rowcol2,
  186.     XtVaTypedArg, XmNtitleString, XmRString, "Cubes", 6,
  187.     XmNminimum, MINCUBES,
  188.     XmNmaximum, MAXCUBES,
  189.     XmNvalue, MINCUBES,
  190.     XmNshowValue, True,
  191.     XmNorientation, XmHORIZONTAL,
  192.     NULL);
  193.   XtAddCallback(cubes, XmNvalueChangedCallback, CubesSlider, NULL);
  194.   rowcol3 = XtVaCreateManagedWidget("Rowcol3", xmRowColumnWidgetClass, panel2,
  195.     XmNnumColumns, 1,    
  196.     XmNorientation, XmHORIZONTAL,    
  197.     XmNpacking, XmPACK_COLUMN,    
  198.     NULL);
  199.   orientSwitch = XtVaCreateManagedWidget ("Orient",
  200.     xmToggleButtonWidgetClass, rowcol3,
  201.     NULL);
  202.   XtAddCallback(orientSwitch, XmNvalueChangedCallback, OrientToggle, NULL);
  203.   practiceSwitch = XtVaCreateManagedWidget ("Practice",  
  204.     xmToggleButtonWidgetClass, rowcol3,  
  205.     NULL);  
  206.   XtAddCallback(practiceSwitch, XmNvalueChangedCallback, PracticeToggle, NULL);
  207.   rowcol4 = XtVaCreateManagedWidget("Rowcol4", xmRowColumnWidgetClass, panel2,
  208.     NULL);
  209.   message = XtVaCreateManagedWidget("Play Rubik's Cube! (use mouse and keypad)",
  210.     xmLabelWidgetClass, rowcol4,
  211.     NULL);
  212.  
  213.   rubik2d = XtCreateManagedWidget("rubik", rubik2dWidgetClass, panel,
  214.     NULL, 0);
  215.   XtVaSetValues(rubik2d,
  216.     XtNheight, 200,
  217.     NULL);
  218.   XtAddCallback(rubik2d, XtNselectCallback, CallbackRubik, NULL);
  219.   rubik3d = XtCreateManagedWidget("rubik", rubik3dWidgetClass, panel,
  220.     NULL, 0);
  221.   XtVaSetValues(rubik3d,
  222.     XtNheight, 200,
  223.     NULL);
  224.   XtAddCallback(rubik3d, XtNselectCallback, CallbackRubik, NULL);
  225.   Initialize();
  226.   XtRealizeWidget(toplevel);
  227.   XGrabButton(XtDisplay(rubik2d), AnyButton, AnyModifier, XtWindow(rubik2d),
  228.     TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
  229.     GrabModeAsync, GrabModeAsync, XtWindow(rubik2d),
  230.     XCreateFontCursor(XtDisplay(rubik2d), XC_crosshair));
  231.   XGrabButton(XtDisplay(rubik3d), AnyButton, AnyModifier, XtWindow(rubik3d),
  232.     TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
  233.     GrabModeAsync, GrabModeAsync, XtWindow(rubik3d),
  234.     XCreateFontCursor(XtDisplay(rubik3d), XC_crosshair));
  235.   XtMainLoop();
  236.  
  237. #ifdef VMS
  238.   return 1;
  239. #else
  240.   return 0;
  241. #endif
  242. }
  243.  
  244. /* There's probably a better way to assure that they are the same but
  245.    I don't know it off hand. */
  246. static void MakeEquivalent(size, orient, practice)
  247.   int *size;
  248.   Boolean *orient, *practice;
  249. {
  250.   Boolean mono;
  251.   Pixel foreground, background, pieceBorder;
  252.   String faceColor[MAXFACES];
  253.  
  254.   XtVaGetValues(rubik2d,
  255.     XtNsize, size,
  256.     XtNorient, orient,
  257.     XtNpractice, practice,
  258.     XtNmono, &mono,
  259.     XtNforeground, &foreground,
  260.     XtNbackground, &background,
  261.     XtNpieceBorder, &pieceBorder,
  262.     XtNfaceColor0, &(faceColor[0]),
  263.     XtNfaceColor1, &(faceColor[1]),
  264.     XtNfaceColor2, &(faceColor[2]),
  265.     XtNfaceColor3, &(faceColor[3]),
  266.     XtNfaceColor4, &(faceColor[4]),
  267.     XtNfaceColor5, &(faceColor[5]),
  268.     NULL);
  269.   XtVaSetValues(rubik2d,
  270.     XtNdirection, RUBIK_IGNORE,
  271.     XtNstart, FALSE,
  272.     NULL);
  273.   XtVaSetValues(rubik3d,
  274.     XtNsize, *size,
  275.     XtNorient, *orient,
  276.     XtNmono, mono,
  277.     XtNdirection, RUBIK_IGNORE,
  278.     XtNpractice, *practice,
  279.     XtNstart, FALSE,
  280.     XtNforeground, foreground,
  281.     XtNbackground, background,
  282.     XtNpieceBorder, pieceBorder,
  283.     XtNfaceColor0, faceColor[0],
  284.     XtNfaceColor1, faceColor[1],
  285.     XtNfaceColor2, faceColor[2],
  286.     XtNfaceColor3, faceColor[3],
  287.     XtNfaceColor4, faceColor[4],
  288.     XtNfaceColor5, faceColor[5],
  289.     NULL);
  290. }
  291.  
  292. static void Initialize()
  293. {
  294.   int size;
  295.   Boolean orient, practice;
  296.  
  297.   MakeEquivalent(&size, &orient, &practice);
  298.   if (size <= MAXCUBES)
  299.     XmScaleSetValue(cubes, size);
  300.   XmToggleButtonSetState(orientSwitch, orient, True);
  301.   XmToggleButtonSetState(practiceSwitch, practice, True);
  302.   ReadRecords();
  303.   PrintRecord(size, orient, practice);
  304. }
  305.  
  306. static void CallbackRubik(w, clientData, callData)
  307.   Widget w;
  308.   caddr_t clientData;
  309.   rubikCallbackStruct *callData;
  310. {
  311.   int size;
  312.   Boolean orient, practice, start;
  313.   Widget otherw;
  314.  
  315.   if (w == rubik2d)
  316.     otherw = rubik3d;
  317.   else /* (w == rubik3d) */
  318.     otherw = rubik2d;
  319.   XtVaGetValues(w,
  320.     XtNsize, &size,
  321.     XtNorient, &orient,
  322.     XtNpractice, &practice,
  323.     XtNstart, &start,
  324.     NULL);
  325.   (void) strcpy(messageDsp, "");
  326.   switch (callData->reason) {
  327.     case RUBIK_RESTORE:
  328.       XtSetArg(arg[0], XtNdirection, RUBIK_RESTORE);
  329.       XtSetValues(otherw, arg, 1);
  330.       XtSetValues(w, arg, 1);
  331.       movesDsp = 0;
  332.       break;
  333.     case RUBIK_RESET:
  334.       movesDsp = 0;
  335.       break;
  336.     case RUBIK_ILLEGAL:
  337.       if (practice || start)
  338.         (void) strcpy(messageDsp, "Illegal move");
  339.       else
  340.         (void) strcpy(messageDsp, "Randomize to start");
  341.       break;
  342.     case RUBIK_MOVED:
  343.       movesDsp++;
  344.       XtSetArg(arg[0], XtNstart, TRUE);
  345.       XtSetArg(arg[1], XtNface, callData->face);
  346.       XtSetArg(arg[2], XtNpos, callData->position);
  347.       XtSetArg(arg[3], XtNdirection, callData->direction);
  348.       XtSetValues(otherw, arg, 4);
  349.       XtSetValues(w, arg, 1);
  350.       break;
  351.     case RUBIK_CONTROL:
  352.       XtSetArg(arg[0], XtNface, callData->face);
  353.       XtSetArg(arg[1], XtNpos, callData->position);
  354.       XtSetArg(arg[2], XtNdirection, callData->direction);
  355.       XtSetValues(otherw, arg, 3);
  356.       return;
  357.     case RUBIK_SOLVED:
  358.       if (practice)
  359.         movesDsp = 0;
  360.       else { 
  361.         if (HandleSolved(movesDsp, size, orient))
  362.           (void) sprintf(messageDsp, "Congratulations %s!!", getlogin());
  363.         else
  364.           (void) strcpy(messageDsp, "Solved!");
  365.       }
  366.       XtSetArg(arg[0], XtNstart, FALSE);
  367.       XtSetValues(w, arg, 1);
  368.       XtSetValues(otherw, arg, 1);
  369.       break;
  370.     case RUBIK_PRACTICE:
  371.       movesDsp = 0;
  372.       practice = !practice;
  373.       if (!practice)
  374.         (void) strcpy(messageDsp, "Randomize to start");
  375.       PrintRecord(size, orient, practice);
  376.       XtSetArg(arg[0], XtNpractice, practice);
  377.       XtSetArg(arg[1], XtNstart, FALSE);
  378.       XtSetValues(w, arg, 2);
  379.       XtSetValues(otherw, arg, 2);
  380.       XmToggleButtonSetState(practiceSwitch, practice, True);
  381.       break;
  382.     case RUBIK_RANDOMIZE:
  383.       movesDsp = 0;
  384.       XtSetArg(arg[0], XtNpractice, FALSE);
  385.       XtSetArg(arg[1], XtNstart, FALSE);
  386.       XtSetValues(w, arg, 2);
  387.       XtSetValues(otherw, arg, 2);
  388.       break; 
  389.     case RUBIK_DEC:
  390.       movesDsp = 0;
  391.       size--;
  392.       PrintRecord(size, orient, practice);
  393.       XtSetArg(arg[0], XtNsize, size);
  394.       XtSetValues(w, arg, 1);
  395.       XtSetValues(otherw, arg, 1);
  396.       if (size <= MAXCUBES)
  397.         XmScaleSetValue(cubes, size);
  398.       break;
  399.     case RUBIK_ORIENT:
  400.       movesDsp = 0;
  401.       orient = !orient;
  402.       PrintRecord(size, orient, practice);
  403.       XtSetArg(arg[0], XtNorient, orient);
  404.       XtSetValues(w, arg, 1);
  405.       XtSetValues(otherw, arg, 1);
  406.       XmToggleButtonSetState(orientSwitch, orient, True);
  407.       break;
  408.     case RUBIK_INC:
  409.       movesDsp = 0;
  410.       size++;
  411.       PrintRecord(size, orient, practice);
  412.       XtSetArg(arg[0], XtNsize, size);
  413.       XtSetValues(w, arg, 1);
  414.       XtSetValues(otherw, arg, 1);
  415.       if (size <= MAXCUBES)
  416.         XmScaleSetValue(cubes, size);
  417.       break;
  418.     case RUBIK_COMPUTED:
  419.       XtSetArg(arg[0], XtNstart, FALSE);
  420.       XtSetValues(w, arg, 1);
  421.       XtSetValues(otherw, arg, 1);
  422.       break;
  423.     case RUBIK_UNDO:
  424.       movesDsp--;
  425.       XtSetArg(arg[0], XtNstart, TRUE);
  426.       XtSetArg(arg[1], XtNface, callData->face);
  427.       XtSetArg(arg[2], XtNpos, callData->position);
  428.       XtSetArg(arg[3], XtNdirection, callData->direction);
  429.       XtSetValues(otherw, arg, 4);
  430.       XtSetValues(w, arg, 1);
  431.       break;
  432.   }
  433.   motif_printf(message, "%s", messageDsp);
  434.   motif_printf(moves, "%d", movesDsp);
  435. }
  436.  
  437. static void CubesSlider(w, clientData, cbs)
  438.   Widget w;
  439.   XtPointer clientData;
  440.   XmScaleCallbackStruct *cbs;
  441. {
  442.   int size = cbs->value, old;
  443.   Boolean orient, practice;
  444.  
  445.   XtVaGetValues(rubik2d,
  446.     XtNsize, &old,
  447.     XtNorient, &orient,
  448.     XtNpractice, &practice,
  449.     NULL);
  450.   if (old != size) {
  451.     XtVaSetValues(rubik2d,
  452.       XtNsize, size,
  453.       NULL);
  454.     XtVaSetValues(rubik3d,
  455.       XtNsize, size,
  456.       NULL);
  457.     movesDsp = 0;
  458.     motif_printf(moves, "%d", movesDsp);
  459.     PrintRecord(size, orient, practice);
  460.   }
  461. }
  462.  
  463. static void OrientToggle(w, clientData, cbs)
  464.   Widget w;
  465.   XtPointer clientData;
  466.   XmToggleButtonCallbackStruct *cbs;
  467. {
  468.   int size;
  469.   Boolean orient = cbs->set, practice;
  470.  
  471.   XtVaGetValues(rubik2d,
  472.     XtNsize, &size,
  473.     XtNpractice, &practice,
  474.     NULL);
  475.   XtVaSetValues(rubik2d,
  476.     XtNorient, orient,
  477.     NULL);
  478.   XtVaSetValues(rubik3d,
  479.     XtNorient, orient,
  480.     NULL);
  481.   movesDsp = 0;
  482.   motif_printf(moves, "%d", movesDsp);
  483.   PrintRecord(size, orient, practice);
  484. }
  485.  
  486. static void PracticeToggle(w, clientData, cbs)
  487.   Widget w;
  488.   XtPointer clientData;
  489.   XmToggleButtonCallbackStruct *cbs;
  490. {
  491.   int size;
  492.   Boolean orient, practice = cbs->set;
  493.  
  494.   XtVaSetValues(rubik2d,
  495.     XtNpractice, practice,
  496.     XtNstart, FALSE,
  497.     NULL);
  498.   XtVaSetValues(rubik3d,
  499.     XtNpractice, practice,
  500.     XtNstart, FALSE,
  501.     NULL);
  502.   XtVaGetValues(rubik2d,
  503.     XtNsize, &size,
  504.     XtNpractice, &orient,
  505.     NULL);
  506.   movesDsp = 0;
  507.   motif_printf(moves, "%d", movesDsp);
  508.   if (!practice)
  509.     (void) strcpy(messageDsp, "Randomize to start");
  510.   PrintRecord(size, orient, practice);
  511. }
  512.  
  513. static void PrintRecord(size, orient, practice)
  514.   int size;
  515.   Boolean orient, practice;
  516. {
  517.   int i = (orient) ? 1 : 0;
  518.   int j = size - MINCUBES;
  519.  
  520.   if (practice)
  521.     motif_printf(record, "practice");
  522.   else if (size > MAXCUBES)
  523.     motif_printf(record, "NOT RECORDED");
  524.   else if (rubikRecord[i][j] >= MAXRECORD)
  525.     motif_printf(record, "NEVER");
  526.   else
  527.     motif_printf(record, "%d", rubikRecord[i][j]);
  528. }
  529.  
  530. static int HandleSolved(counter, size, orient)
  531.   int counter, size;
  532.   Boolean orient;
  533. {
  534.   int i = (orient) ? 1 : 0;
  535.   int j = size - MINCUBES;
  536.  
  537.   if (size <= MAXCUBES && counter < rubikRecord[i][j]) {
  538.     rubikRecord[i][j] = counter;
  539.     if (size < 2 || (orient && rubikRecord[i][j] < rubikRecord[!i][j]))
  540.       rubikRecord[!i][j] = counter;
  541.     WriteRecords();
  542.     PrintRecord(size, orient, FALSE);
  543.     return TRUE;
  544.   }
  545.   return FALSE;
  546. }
  547.  
  548. static void ReadRecords()
  549. {
  550.   FILE *fp;
  551.   int i, n, orient;
  552.  
  553.   for (orient = 0; orient < 2; orient++)
  554.     for (i = 0; i < MAXCUBES - MINCUBES + 1; i++)
  555.       rubikRecord[orient][i] = MAXRECORD;
  556.   if ((fp = fopen(SCOREFILE, "r")) == NULL)
  557.     motif_printf(message, "Can not open %s, taking defaults.", SCOREFILE);
  558.   else {
  559.     for (orient = 0; orient < 2; orient++)
  560.       for (i = 0; i < MAXCUBES - MINCUBES + 1; i++) {
  561.         (void) fscanf(fp, "%d", &n);
  562.         rubikRecord[orient][i] = n;
  563.       }
  564.     (void) fclose(fp);
  565.   }
  566. }
  567.  
  568. static void WriteRecords()
  569. {
  570.   FILE *fp;
  571.   int i, orient;
  572.  
  573.   if ((fp = fopen(SCOREFILE, "w")) == NULL)
  574.     motif_printf(message, "Can not write to %s.", SCOREFILE);
  575.   else {
  576.     for (orient = 0; orient < 2; orient++) {
  577.       for (i = 0; i < MAXCUBES - MINCUBES + 1; i++)
  578.         (void) fprintf(fp, "%d ", rubikRecord[orient][i]);
  579.       (void) fprintf(fp, "\n");
  580.     }
  581.     (void) fclose(fp);
  582.   }
  583. }
  584.  
  585. #include <varargs.h>
  586. static void motif_printf(va_alist)
  587.   va_dcl
  588. {
  589.   Widget w;
  590.   char *format;
  591.   va_list args;
  592.   char str[1000];
  593.   Arg wargs[10];
  594.   XmString xmstr;
  595.  
  596.   va_start(args);
  597.   w = va_arg(args, Widget);
  598.   if (!XtIsSubclass(w, xmLabelWidgetClass))
  599.     XtError("motif_printf() requires a Label Widget");
  600.   format = va_arg(args, char *);
  601.   (void) vsprintf(str, format, args);
  602.   xmstr = XmStringCreateLtoR(str, XmSTRING_DEFAULT_CHARSET);
  603.   XtSetArg(wargs[0], XmNlabelString, xmstr);
  604.   XtSetValues(w, wargs, 1);
  605.   va_end(args);
  606. }
  607.